package com.borzaindustries.mkdummy;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.*;
import android.content.*;
import android.content.DialogInterface.OnCancelListener;
import android.os.*;
import android.view.*;
import android.widget.*;
import android.view.View.*;

public class CreateBinaryDummy extends Activity implements Runnable {
	// CONSTANTS
	public final String SIZE = "SIZE";
	public final String DIRECTORY = "DIRECTORY";
	public final String NAME = "NAME";
	public final String FILE_TYPE_IS_BINARY = "FILE_TYPE";
	public final int PROGRESS_DIALOG = 0;
	public final int CONFIRM_OVEWRTITE = 1;

	public final int TYPE_RANDOM_BINARY = 0;
	public final int TYPE_EMPTY_FILE = 1;

	// FIELDS
	private File file;
	private int size;
	private volatile boolean cancel = false;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.create_binary_dummy);
		attachEventListeners();
		restorePrefs();
	}

	private void attachEventListeners() {
		this.setTitle(this.getString(R.string.create_binary_title));
		((ImageButton) findViewById(R.id.button_browse_dir))
				.setOnClickListener(new OnClickListener() {
					public void onClick(View arg0) {
						browseDir();
					}
				});

		((ImageButton) findViewById(R.id.button_random_name))
				.setOnClickListener(new OnClickListener() {
					public void onClick(View arg0) {
						randomName();
					}
				});
		((ImageButton) findViewById(R.id.button_random_size))
				.setOnClickListener(new OnClickListener() {
					public void onClick(View arg0) {
						randomSize();
					}
				});
		((Button) findViewById(R.id.create))
				.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View arg0) {
						createDummy();
					}
				});
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case CONFIRM_OVEWRTITE:
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setMessage(
					getString(R.string.file_already_exists_overwrite,
							file.getName()))
					.setTitle(R.string.app_name)
					.setCancelable(true)
					.setPositiveButton(R.string.ok,
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									// continue with dummy
									dialog.dismiss();
									startCreateDummyThread();
								}
							})
					.setNegativeButton(R.string.cancel,
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									dialog.cancel();
								}
							});
			return builder.create();
		case PROGRESS_DIALOG:
			ProgressDialog progressDialog = new ProgressDialog(this);
			progressDialog
					.setMessage(this.getText(R.string.creating_file_wait));
			progressDialog.setCancelable(true);
			progressDialog.setOnCancelListener(new OnCancelListener() {
				@Override
				public void onCancel(DialogInterface dialog) {
					cancel = true;
				}
			});
			return progressDialog;
		default:
			return null;
		}
	}

	// PREFERENCES
	private void restorePrefs() {
		SharedPreferences settings = getPreferences(MODE_PRIVATE);
		// name from preferences
		String name = settings.getString(NAME, "");
		if (name == "")
			randomName();
		else
			((EditText) findViewById(R.id.edit_name)).setText(name);
		// check for last size in preferences
		String size = settings.getString(SIZE, "");
		if (size == "")
			randomSize();
		else
			((EditText) findViewById(R.id.edit_size)).setText(size);
		// check for directory in preferences
		String directory = settings.getString(DIRECTORY, "");
		if (directory == "")
			directory = "/sdcard"; // default to /sdcard
		setDirectory(directory);
		// set file type
		boolean fileTypeBinary = settings.getBoolean(FILE_TYPE_IS_BINARY, true);
		((RadioButton) findViewById(R.id.file_binary))
				.setChecked(fileTypeBinary);
		((RadioButton) findViewById(R.id.file_empty))
				.setChecked(!fileTypeBinary);
	}

	@Override
	protected void onResume() {
		super.onResume();
		restorePrefs();
	}

	@Override
	protected void onPause() {
		super.onPause();
		SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
		editor.putString(NAME, getName());
		editor.putString(SIZE, getSizeString());
		editor.putString(DIRECTORY, getDirectory());
		editor.putBoolean(FILE_TYPE_IS_BINARY, isFileTypeBinary());
		editor.commit();
	}

	private String getSizeString() {
		return ((EditText) findViewById(R.id.edit_size)).getText().toString();
	}

	private String getDirectory() {
		return ((EditText) findViewById(R.id.edit_dir)).getText().toString();
	}

	private void setDirectory(String directory) {
		((EditText) findViewById(R.id.edit_dir)).setText(directory);
	}

	private String getName() {
		return ((EditText) findViewById(R.id.edit_name)).getText().toString();
	}

	private boolean isFileTypeBinary() {
		return ((RadioButton) findViewById(R.id.file_binary)).isChecked();
	}

	// DIRECTORY BROWSING
	private void browseDir() {
		// decode test string
		String path = getDirectory();
		Intent intent = new Intent(getBaseContext(), DirectoryBrowser.class);
		intent.putExtra(DirectoryBrowser.SELECTED_PATH, path);
		startActivityForResult(intent, DirectoryBrowser.BROWSE_DIR);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == DirectoryBrowser.BROWSE_DIR) {
			if (resultCode != RESULT_OK)
				return;
			String directory = data
					.getStringExtra(DirectoryBrowser.SELECTED_PATH);
			setDirectory(directory);
		}
	}

	private void randomName() {
		String s = Randomizer.getInstance().getShortRandomString() + ".tmp";
		((EditText) findViewById(R.id.edit_name)).setText(s);
	}

	private void randomSize() {
		int size = Randomizer.getInstance().getRandomNumber(1, 100000);
		((EditText) findViewById(R.id.edit_size)).setText(SizeFormatter
				.formatSizeString(size));
	}

	// OPTIONS MENU
	@Override
	public final boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.create_single_menu, menu);
		return true;
	}

	@Override
	public final boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.ok:
			createDummy();
			return true;
		case R.id.cancel:
			finish();
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private void createDummy() {
		String directory = getDirectory();
		String name = getName();
		try {
			size = SizeFormatter.decodeSizeString(getSizeString());
		} catch (Exception e) {
			Toast.makeText(this, "File size is in invalid format",
					Toast.LENGTH_SHORT).show();
			return;
		}
		file = new File(directory, name);
		if (file.exists()) {
			showDialog(CONFIRM_OVEWRTITE);
			return;
		}
		startCreateDummyThread();
	}

	private void startCreateDummyThread() {
		showDialog(PROGRESS_DIALOG);
		Thread thread = new Thread(this);
		thread.start();
	}

	// DUMMY CREATE THREAD
	private Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			dismissDialog(PROGRESS_DIALOG);
			if (msg.what == RESULT_OK) {
				Toast.makeText(
						CreateBinaryDummy.this,
						CreateBinaryDummy.this.getString(
								R.string.file_created_successfully,
								file.getName()), Toast.LENGTH_SHORT).show();
			} else
				Toast.makeText(
						CreateBinaryDummy.this,
						CreateBinaryDummy.this
								.getString(R.string.file_not_created),
						Toast.LENGTH_SHORT).show();
		}
	};

	@Override
	public void run() {
		try {
			boolean result = createFile(file, size, isFileTypeBinary());
			if (result) {
				handler.sendEmptyMessage(RESULT_OK);
			} else {
				handler.sendEmptyMessage(RESULT_CANCELED);
			}
		} catch (Exception e) {
			handler.sendEmptyMessage(RESULT_CANCELED);
		}
	}

	private boolean createFile(File file, int size, boolean useRandomizer)
			throws IOException {
		// create file in random BUFSIZE blocks + rest
		final int BUFSIZE = 16384;
		byte[] buffer = new byte[BUFSIZE];
		FileOutputStream fos = new FileOutputStream(file);
		// write complete blocks
		int wholeBlockCount = size / BUFSIZE;
		for (int i = 0; i < wholeBlockCount; i++) {
			if (cancel) {
				// delete the file
				fos.close();
				file.delete();
			}
			if (useRandomizer)
				Randomizer.getInstance().fillByteArray(buffer);
			fos.write(buffer, 0, BUFSIZE);
		}
		// write the remainder
		int remainingByteCount = size % BUFSIZE;
		if (remainingByteCount > 0) {
			if (useRandomizer)
				Randomizer.getInstance().fillByteArray(buffer);
			fos.write(buffer, 0, remainingByteCount);
		}
		// cleanup
		fos.close();
		return true;
	}
}